/*******************************************************************************
 *                                 ZLG
 *                       ----------------------------
 *                       innovating embedded platform
 *
 * Copyright (c) 2001-present Guangzhou ZHIYUAN Electronics Co., Ltd.
 * ALL rights reserved.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *
 * The License of this software follows LGPL v2.1, See the LICENSE for more details:
 * https://opensource.org/licenses/LGPL-2.1
 *
 * Contact information:
 * web site:    http://www.zlg.cn/
 *******************************************************************************/
#include "riscv/riscv_core.h"
#include "core/include/hpm6e00_regs_csr.h"

/**
 * \brief 保存调用者环境
 */
#define CALLER_SAVE()              \
        addi        sp, sp, -68;   \
        sw          ra, 0(sp);     \
        sw          tp, 4(sp);     \
        sw          t0, 8(sp);     \
        sw          t1, 12(sp);    \
        sw          t2, 16(sp);    \
        sw          t3, 20(sp);    \
        sw          t4, 24(sp);    \
        sw          t5, 28(sp);    \
        sw          t6, 32(sp);    \
        sw          a0, 36(sp);    \
        sw          a1, 40(sp);    \
        sw          a2, 44(sp);    \
        sw          a3, 48(sp);    \
        sw          a4, 52(sp);    \
        sw          a5, 56(sp);    \
        sw          a6, 60(sp);    \
        sw          a7, 64(sp);

/**
 * \brief 加载调用者环境
 */
#define CALLER_LOAD()              \
        lw          ra, 0(sp);     \
        lw          tp, 4(sp);     \
        lw          t0, 8(sp);     \
        lw          t1, 12(sp);    \
        lw          t2, 16(sp);    \
        lw          t3, 20(sp);    \
        lw          t4, 24(sp);    \
        lw          t5, 28(sp);    \
        lw          t6, 32(sp);    \
        lw          a0, 36(sp);    \
        lw          a1, 40(sp);    \
        lw          a2, 44(sp);    \
        lw          a3, 48(sp);    \
        lw          a4, 52(sp);    \
        lw          a5, 56(sp);    \
        lw          a6, 60(sp);    \
        lw          a7, 64(sp);    \
        addi        sp, sp, 68;

#if __riscv_flen

#if __riscv_flen > 32
#define FP_OFFSET_MUL_FACTOR                2
#define RV_OP_FP_STOREREG                   fsd
#define RV_OP_FP_LOADREG                    fld
#else
#define FP_OFFSET_MUL_FACTOR                1
#define RV_OP_FP_STOREREG                   fsw
#define RV_OP_FP_LOADREG                    flw
#endif

#define MSTATUS_FP_SAVE()                                       \
        csrr        a0, mstatus;                                \
        addi        sp, sp, -4;                                 \
        sw          a0, 0(sp);                                  \
        li          a1, ~CSR_MSTATUS_FS_MASK;                   \
        li          a2, CSR_MSTATUS_FS_INIT;                    \
        and         a0, a0, a1;                                 \
        or          a0, a0, a2;                                 \
        csrw        mstatus, a0;                                \

#define MSTATUS_FP_LOAD()                                       \
        lw          a0, 0(sp);                                  \
        addi        sp,sp,4;                                    \
        csrw        mstatus,a0;                                 \


/**
 * \brief 保存调用者浮点环境
 */
#define CALLER_FP_SAVE()                                               \
        csrr               a0, mstatus;                                \
        li                 a1, CSR_MSTATUS_FS_MASK;                    \
        and                a0, a0, a1;                                 \
        bne                a0, a1, 1f;                                 \
        frcsr              a2 ;                                        \
        addi               sp, sp, -(21 * 4 * FP_OFFSET_MUL_FACTOR);   \
        sw                 a2,   (0 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_STOREREG  ft0,  (1 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_STOREREG  ft1,  (2 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_STOREREG  ft2,  (3 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_STOREREG  ft3,  (4 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_STOREREG  ft4,  (5 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_STOREREG  ft5,  (6 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_STOREREG  ft6,  (7 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_STOREREG  ft7,  (8 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_STOREREG  ft8,  (9 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_STOREREG  ft9,  (10 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
        RV_OP_FP_STOREREG  ft10, (11 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
        RV_OP_FP_STOREREG  ft11, (12 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
        RV_OP_FP_STOREREG  fa0,  (13 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
        RV_OP_FP_STOREREG  fa1,  (14 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
        RV_OP_FP_STOREREG  fa2,  (15 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
        RV_OP_FP_STOREREG  fa3,  (16 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
        RV_OP_FP_STOREREG  fa4,  (17 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
        RV_OP_FP_STOREREG  fa5,  (18 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
        RV_OP_FP_STOREREG  fa6,  (19 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
        RV_OP_FP_STOREREG  fa7,  (20 * 4 * FP_OFFSET_MUL_FACTOR)(sp);  \
1:

#define CALLER_FP_AFTER_C_TRAP_LOAD()                                  \
        /* save mstatus after c isr to a1 */                           \
        csrr              a1, mstatus;                                 \
        MSTATUS_FP_LOAD();                                             \
        /* now a0 is mstatus */                                        \
        /* now a1 is mstatus after c isr */                            \
        li                a2, CSR_MSTATUS_FS_MASK;                     \
        and               a0, a0, a2;                                  \
        bne               a0, a2, 2f;                                  \
        li                a3, CSR_MSTATUS_FS_INIT;                     \
        and               a1, a1, a2;                                  \
        beq               a1, a3, 1f;                                  \
        RV_OP_FP_LOADREG  ft0,  (1 * 4 * FP_OFFSET_MUL_FACTOR)(sp);    \
        RV_OP_FP_LOADREG  ft1,  (2 * 4 * FP_OFFSET_MUL_FACTOR)(sp);    \
        RV_OP_FP_LOADREG  ft2,  (3 * 4 * FP_OFFSET_MUL_FACTOR)(sp);    \
        RV_OP_FP_LOADREG  ft3,  (4 * 4 * FP_OFFSET_MUL_FACTOR)(sp);    \
        RV_OP_FP_LOADREG  ft4,  (5 * 4 * FP_OFFSET_MUL_FACTOR)(sp);    \
        RV_OP_FP_LOADREG  ft5,  (6 * 4 * FP_OFFSET_MUL_FACTOR)(sp);    \
        RV_OP_FP_LOADREG  ft6,  (7 * 4 * FP_OFFSET_MUL_FACTOR)(sp);    \
        RV_OP_FP_LOADREG  ft7,  (8 * 4 * FP_OFFSET_MUL_FACTOR)(sp);    \
        RV_OP_FP_LOADREG  ft8,  (9 * 4 * FP_OFFSET_MUL_FACTOR)(sp);    \
        RV_OP_FP_LOADREG  ft9,  (10 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_LOADREG  ft10, (11 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_LOADREG  ft11, (12 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_LOADREG  fa0,  (13 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_LOADREG  fa1,  (14 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_LOADREG  fa2,  (15 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_LOADREG  fa3,  (16 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_LOADREG  fa4,  (17 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_LOADREG  fa5,  (18 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_LOADREG  fa6,  (19 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        RV_OP_FP_LOADREG  fa7,  (20 * 4 * FP_OFFSET_MUL_FACTOR)(sp);   \
        lw          a4, (0 * 4 * FP_OFFSET_MUL_FACTOR)(sp);            \
        fscsr       zero, a4;                                          \
1:                                                                     \
        addi        sp, sp, (21 * 4 * FP_OFFSET_MUL_FACTOR);           \
2:                                                                     \


#endif

 /**
 * \brief 复位处理函数
 */
    .global reset_handler;
    .section .reset.handler, "ax"
    .type reset_handler, %function;
    .func
reset_handler:
    # 将当前的选项设置存入栈中
    .option     push
    # 不允许链接器优化
    .option     norelax
    # 初始化全局指针
    la          gp, __global_pointer$
    .option     pop

    /* 复位 mstatus 寄存器值为 0*/
    csrrw       x0, mstatus, x0

#ifdef __riscv_flen
    # 使能 FPU
    li          t0, CSR_MSTATUS_FS_MASK
    csrrs       t0, mstatus, t0
    # 初始化 FSCSR(浮点交换控制和状态寄存器)
    fscsr       zero
#endif

    # 初始化栈指针
    la          t0, __stack_top__
    mv          sp, t0

    # 使能 icache
    call        l1c_ic_enable
    # 使能并无效化 dcache
    call        l1c_dc_enable
    call        l1c_dc_invalidate_all

    # 段初始化
    call        c_base_runtime_init

#ifndef NO_CLEANUP_AT_START
    /* clean up */
    call        irq_clean_up
#endif

#ifdef __nds_execit
    /* Initialize EXEC.IT table */
    la          t0, _ITB_BASE_
    csrw        uitb, t0
#endif
    csrw        mscratch, 0

    # 初始化机器 trap 向量基地址 */
    la          t0, __vector_table
    csrw        mtvec, t0
    # 设置 PLIC(Platform-Level Interrupt Controller 平台中断控制器) 向量模式
    csrsi       CSR_MMISC_CTL, 2
    # 系统初始化
    call        system_init
    # 主函数
    call        main
    # 死循环
    j           .
    .endfunc;.text


    # 中断处理函数
    .global isr_handler
    .section .text.isr_handler
    .type isr_handler, %function
    .func
isr_handler:
    CALLER_SAVE();
#if __riscv_flen
    CALLER_FP_SAVE();
    MSTATUS_FP_SAVE();
#endif

    csrr        a0, mcause
    li          t0, CSR_MCAUSE_EXCEPTION_CODE_MASK
    and         a0, a0, t0
    # 中断号是参数
    call        intc_gen_isr

#if __riscv_flen
    //MSTATUS_FP_LOAD();
    CALLER_FP_AFTER_C_TRAP_LOAD();
#endif
    CALLER_LOAD();
    mret
    .endfunc;.text


    .global trap_distribute
    .section .text.trap_distribute
    .type trap_distribute, %function
    .func
trap_distribute:
    # 4字节对齐
    .align 2
    call        irq_trap_handler
    j           .
    .endfunc;.text

    #自陷向量表
    .section .text.vector, "a"
    .global __vector_table
    .align 9
__vector_table:
    .word freertos_risc_v_trap_handler     /* trap(自陷)*/
    .word isr_handler         /* GPIO0_A 中断处理函数 */
    .word isr_handler         /* GPIO0_B 中断处理函数 */
    .word isr_handler         /* GPIO0_C 中断处理函数 */
    .word isr_handler         /* GPIO0_D 中断处理函数 */
    .word isr_handler         /* GPIO0_E 中断处理函数 */
    .word isr_handler         /* GPIO0_F 中断处理函数 */
    .word isr_handler         /* GPIO0_V 中断处理函数 */
    .word isr_handler         /* GPIO0_W 中断处理函数 */
    .word isr_handler         /* GPIO0_X 中断处理函数 */
    .word isr_handler         /* GPIO0_Y 中断处理函数 */
    .word isr_handler         /* GPIO0_Z 中断处理函数 */
    .word isr_handler         /* GPIO1_A 中断处理函数 */
    .word isr_handler         /* GPIO1_B 中断处理函数 */
    .word isr_handler         /* GPIO1_C 中断处理函数 */
    .word isr_handler         /* GPIO1_D 中断处理函数 */
    .word isr_handler         /* GPIO1_E 中断处理函数 */
    .word isr_handler         /* GPIO1_F 中断处理函数 */
    .word isr_handler         /* GPIO1_V 中断处理函数 */
    .word isr_handler         /* GPIO1_W 中断处理函数 */
    .word isr_handler         /* GPIO1_X 中断处理函数 */
    .word isr_handler         /* GPIO1_Y 中断处理函数 */
    .word isr_handler         /* GPIO1_Z 中断处理函数 */
    .word isr_handler         /* GPTMR0 中断处理函数 */
    .word isr_handler         /* GPTMR1 中断处理函数 */
    .word isr_handler         /* GPTMR2 中断处理函数 */
    .word isr_handler         /* GPTMR3 中断处理函数 */
    .word isr_handler         /* GPTMR4 中断处理函数 */
    .word isr_handler         /* GPTMR5 中断处理函数 */
    .word isr_handler         /* GPTMR6 中断处理函数 */
    .word isr_handler         /* GPTMR7 中断处理函数 */
    .word isr_handler         /* UART0 中断处理函数  */
    .word isr_handler         /* UART1 中断处理函数  */
    .word isr_handler         /* UART2 中断处理函数  */
    .word isr_handler         /* UART3 中断处理函数  */
    .word isr_handler         /* UART4 中断处理函数  */
    .word isr_handler         /* UART5 中断处理函数  */
    .word isr_handler         /* UART6 中断处理函数  */
    .word isr_handler         /* UART7 中断处理函数  */
    .word isr_handler         /* I2C0 中断处理函数 */
    .word isr_handler         /* I2C1 中断处理函数 */
    .word isr_handler         /* I2C2 中断处理函数 */
    .word isr_handler         /* I2C3 中断处理函数 */
    .word isr_handler         /* SPI0 中断处理函数 */
    .word isr_handler         /* SPI1 中断处理函数 */
    .word isr_handler         /* SPI2 中断处理函数 */
    .word isr_handler         /* SPI3 中断处理函数 */
    .word isr_handler         /* TSNS 中断处理函数  */
    .word isr_handler         /* MBX0A 中断处理函数 */
    .word isr_handler         /* MBX0B 中断处理函数 */
    .word isr_handler         /* MBX1A 中断处理函数 */
    .word isr_handler         /* MBX1B 中断处理函数 */
    .word isr_handler         /* EWDG0 中断处理函数 */
    .word isr_handler         /* EWDG1 中断处理函数 */
    .word isr_handler         /* EWDG2 中断处理函数 */
    .word isr_handler         /* EWDG3 中断处理函数 */
    .word isr_handler         /* HDMA 中断处理函数 */
    .word isr_handler         /* LOBS 中断处理函数 */
    .word isr_handler         /* ADC0 中断处理函数 */
    .word isr_handler         /* ADC1 中断处理函数 */
    .word isr_handler         /* ADC2 中断处理函数 */
    .word isr_handler         /* ADC3 中断处理函数 */
    .word isr_handler         /* ACMP0[0] 中断处理函数 */
    .word isr_handler         /* ACMP0[1] 中断处理函数 */
    .word isr_handler         /* ACMP1[0] 中断处理函数 */
    .word isr_handler         /* ACMP1[1] 中断处理函数 */
    .word isr_handler         /* ACMP2[0] 中断处理函数 */
    .word isr_handler         /* ACMP2[1] 中断处理函数 */
    .word isr_handler         /* ACMP3[0] 中断处理函数 */
    .word isr_handler         /* ACMP3[1] 中断处理函数 */
    .word isr_handler         /* I2S0 中断处理函数 */
    .word isr_handler         /* I2S1 中断处理函数 */
    .word isr_handler         /* DAO 中断处理函数 */
    .word isr_handler         /* PDM 中断处理函数 */
    .word isr_handler         /* UART8 中断处理函数 */
    .word isr_handler         /* UART9 中断处理函数 */
    .word isr_handler         /* UART10 中断处理函数 */
    .word isr_handler         /* UART11 中断处理函数 */
    .word isr_handler         /* UART12 中断处理函数 */
    .word isr_handler         /* UART13 中断处理函数 */
    .word isr_handler         /* UART14 中断处理函数 */
    .word isr_handler         /* UART15 中断处理函数 */
    .word isr_handler         /* I2C4 中断处理函数 */
    .word isr_handler         /* I2C5 中断处理函数 */
    .word isr_handler         /* I2C6 中断处理函数 */
    .word isr_handler         /* I2C7 中断处理函数 */
    .word isr_handler         /* SPI4 中断处理函数 */
    .word isr_handler         /* SPI5 中断处理函数 */
    .word isr_handler         /* SPI6 中断处理函数 */
    .word isr_handler         /* SPI7 中断处理函数 */
    .word isr_handler         /* MCAN0 中断处理函数 */
    .word isr_handler         /* MCAN1 中断处理函数 */
    .word isr_handler         /* MCAN2 中断处理函数 */
    .word isr_handler         /* MCAN3 中断处理函数 */
    .word isr_handler         /* MCAN4 中断处理函数 */
    .word isr_handler         /* MCAN5 中断处理函数 */
    .word isr_handler         /* MCAN6 中断处理函数 */
    .word isr_handler         /* MCAN7 中断处理函数 */
    .word isr_handler         /* PTPC 中断处理函数 */
    .word isr_handler         /* QEI0 中断处理函数 */
    .word isr_handler         /* QEI1 中断处理函数 */
    .word isr_handler         /* QEI2 中断处理函数 */
    .word isr_handler         /* QEI3 中断处理函数 */
    .word isr_handler         /* PWM0 中断处理函数 */
    .word isr_handler         /* PWM1 中断处理函数 */
    .word isr_handler         /* PWM2 中断处理函数 */
    .word isr_handler         /* PWM3 中断处理函数 */
    .word isr_handler         /* RDC0 中断处理函数 */
    .word isr_handler         /* RDC1 中断处理函数 */
    .word isr_handler         /* SDM0 中断处理函数 */
    .word isr_handler         /* SDM1 中断处理函数 */
    .word isr_handler         /* SEI0[0] 中断处理函数 */
    .word isr_handler         /* SEI0[1] 中断处理函数 */
    .word isr_handler         /* SEI0[2] 中断处理函数 */
    .word isr_handler         /* SEI0[3] 中断处理函数 */
    .word isr_handler         /* MTG0 中断处理函数 */
    .word isr_handler         /* MTG1 中断处理函数 */
    .word isr_handler         /* VSC0 中断处理函数 */
    .word isr_handler         /* VSC1 中断处理函数 */
    .word isr_handler         /* CLC0[0] 中断处理函数 */
    .word isr_handler         /* CLC0[1] 中断处理函数 */
    .word isr_handler         /* CLC1[0] 中断处理函数 */
    .word isr_handler         /* CLC1[1] 中断处理函数 */
    .word isr_handler         /* TRGMUX0 中断处理函数 */
    .word isr_handler         /* TRGMUX1 中断处理函数 */
    .word isr_handler         /* ENET0 中断处理函数 */
    .word isr_handler         /* NTMR0 中断处理函数 */
    .word isr_handler         /* USB0 中断处理函数 */
    .word isr_handler         /* TSW[0] 中断处理函数 */
    .word isr_handler         /* TSW[1] 中断处理函数 */
    .word isr_handler         /* TSW[2] 中断处理函数 */
    .word isr_handler         /* TSW[3] 中断处理函数 */
    .word isr_handler         /* TSW_PTP_EVT 中断处理函数 */
    .word isr_handler         /* ESC 中断处理函数 */
    .word isr_handler         /* ESC_SYNC0 中断处理函数 */
    .word isr_handler         /* ESC_SYNC1 中断处理函数 */
    .word isr_handler         /* ESC_RESET 中断处理函数 */
    .word isr_handler         /* XPI0 中断处理函数 */
    .word isr_handler         /* FEMC 中断处理函数 */
    .word isr_handler         /* PPI 中断处理函数 */
    .word isr_handler         /* XDMA 中断处理函数 */
    .word isr_handler         /* FFA 中断处理函数 */
    .word isr_handler         /* SDP 中断处理函数 */
    .word isr_handler         /* RNG 中断处理函数 */
    .word isr_handler         /* PKA 中断处理函数 */
    .word isr_handler         /* PSEC 中断处理函数 */
    .word isr_handler         /* PGPIO 中断处理函数 */
    .word isr_handler         /* PEWDG 中断处理函数 */
    .word isr_handler         /* PTMR 中断处理函数 */
    .word isr_handler         /* PUART 中断处理函数 */
    .word isr_handler         /* FUSE 中断处理函数 */
    .word isr_handler         /* SECMON 中断处理函数 */
    .word isr_handler         /* RTC 中断处理函数 */
    .word isr_handler         /* PAD_WAKEUP 中断处理函数 */
    .word isr_handler         /* BGPIO 中断处理函数 */
    .word isr_handler         /* BVIO 中断处理函数 */
    .word isr_handler         /* BROWNOUT 中断处理函数 */
    .word isr_handler         /* SYSCTL 中断处理函数 */
    .word isr_handler         /* CPU0 中断处理函数 */
    .word isr_handler         /* CPU1 中断处理函数 */
    .word isr_handler         /* DEBUG0 中断处理函数 */
    .word isr_handler         /* DEBUG1 中断处理函数 */


